package cn.mujiankeji.mbrowser.功能.浏览框.webview

import android.app.Activity
import android.content.DialogInterface
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Message
import android.util.Log
import android.view.View
import android.webkit.*
import android.webkit.ConsoleMessage.MessageLevel
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.Keep
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import android.view.ContextThemeWrapper
import cn.mujiankeji.mbrowser.R
import cn.mujiankeji.mbrowser.功能.浏览框.浏览框加载状态
import cn.mujiankeji.mbrowser.功能.浏览框.浏览框状态
import com.blankj.utilcode.util.ActivityUtils
import com.blankj.utilcode.util.Utils
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch


/**
 * 自定义 WebChromeClient 实现，处理 JavaScript 对话框、进度条、标题变化等高级 WebView 功能
 * by Jen. 2020.07.
 */
@Keep // 防止混淆，保留类名和所有成员
class MVueChromeClient(val state : 浏览框状态) : WebChromeClient() {

    var curProgress = 0
    var 延时页面状态检测线程 : Job ?= null

    /**
     * 页面加载进度变化时调用
     * 
     * 当页面加载进度发生变化时触发，newProgress 范围为 0-100
     * 可用于更新进度条、注入脚本等操作
     */
    override fun onProgressChanged(view: WebView?, newProgress: Int) {
        super.onProgressChanged(view, newProgress)
        // 进度相同，表示加载到一定位置了，卡顿了一下下  并不需要再执行往后的操作了
        state.coroutine?.launch {

            // 进度变化就应当自动停止延时检查线程
            延时页面状态检测线程?.cancel()
            延时页面状态检测线程 = null

            // 更新边缘颜色
            launch {
                state.更新界面边缘颜色()
            }

            // 注入脚本判断
            if (!state.状态检测脚本已注入 && newProgress >= 20){
                state.状态检测脚本已注入 = true
                if (state.状态== 浏览框加载状态.初始化){
                    state.更新加载状态(浏览框加载状态.加载开始)
                }
                else{
                    state.请求更新页面状态()
                }
            }

            if (newProgress == 100) {

                // 新接
                if (curProgress >= 20){
                    state.状态检测脚本已注入 = false
                    state.更新界面边缘颜色()
                }

                // 进度完成而页面不一定完成，进度完成时应当实时多次判断界面
                if (curProgress != 100) {
                    延时页面状态检测线程 = launch {
                        // 减少检查次数，使用更合理的间隔
                        val delays = listOf(500L, 1500L)
                        for (delayTime in delays) {
                            if (state.状态 == 浏览框加载状态.加载完毕) break
                            delay(delayTime)
                            state.注入脚本("checkChange()")
                            // 强制刷新视图，但只在必要时进行
                            if (state.状态 != 浏览框加载状态.加载完毕) {
                                (view as? MWebView)?.强制触发渲染()
                            }
                        }
                        延时页面状态检测线程 = null
                    }
                }
                
                // 加载完成时强制触发渲染，但只触发一次
                (view as? MWebView)?.postDelayed({ 
                    if (state.状态 != 浏览框加载状态.加载完毕) {
                        (view as? MWebView)?.强制触发渲染() 
                    }
                }, 300)
            }

            curProgress = newProgress
            // 回调 不可以进度忽大忽小
            if (state.状态 != 浏览框加载状态.加载完毕 && state.加载进度.value < newProgress){
                state.加载进度.value = newProgress
            }
        }
    }

    /**
     * 接收到页面标题时调用
     * 
     * 当网页的标题发生变化时触发
     * 用于更新应用标题栏、标签页标题等
     */
    override fun onReceivedTitle(view: WebView?, title: String?) {
        state.标题.value = title ?: ""
        view?.url?.let {
            state.地址.value = it
        }
    }

    /**
     * 处理 JavaScript 的 prompt() 方法
     * 
     * 显示一个带输入框的对话框，让用户输入内容
     * 返回 true 表示应用已处理，false 表示使用默认处理
     */
    override fun onJsPrompt(view: WebView, url: String?, message: String, defaultValue: String, result: JsPromptResult): Boolean {
        return if (state.响应输入框 == null) false
        else {
            state.响应输入框.invoke(message,defaultValue) {
                if (!it.isNullOrBlank()) result.confirm(it)
                else result.cancel()
            }

            true
        }
    }

    /**
     * 处理 JavaScript 的 confirm() 方法
     * 显示一个确认对话框，用户可以选择确定或取消
     * 返回 true 表示应用已处理，false 表示使用默认处理
     */
    override fun onJsConfirm(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {
        if (state.响应确认框 == null) return false
        else{
            state.响应确认框.invoke(message?:""){

                if (it){
                    result?.confirm()
                }
                else{
                    result?.cancel()
                }
            }
            return true
        }


    }

    /**
     * 处理 JavaScript 的 alert() 方法
     * 
     * 显示一个提示对话框，用户只能点击确定
     * 返回 true 表示应用已处理，false 表示使用默认处理
     */
    override fun onJsAlert(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {
        if (message?.equals("[object HTMLDivElement]",true) == true){
            result?.confirm()
            return true
        }
        ActivityUtils.getTopActivity()?.let { aty->
            val builder = AlertDialog.Builder(aty)
            builder.setMessage(message?:"")
            builder.setPositiveButton("确定") { dialog: DialogInterface?, which: Int ->
            }
            builder.setOnDismissListener {
                result?.confirm()
            }
            builder.show()
        }
        return true
    }

    /**
     * 创建新窗口时调用
     * 
     * 当页面请求打开新窗口时触发（如 window.open() 或 target="_blank"）
     * 返回 true 表示应用已处理，false 表示使用默认处理
     */
    override fun onCreateWindow(webView: WebView, isDialog: Boolean, isUserGesture: Boolean, resultMsg: Message): Boolean {
        val transport = resultMsg.obj as WebView.WebViewTransport
        val v = WebView((webView.parent as View).context)
        v.webViewClient = object : WebViewClient() {
            override fun shouldOverrideUrlLoading(webView: WebView, url: String): Boolean {
                state.响应加载新的页面?.invoke(url)
                return true
            }

            override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
                state.响应加载新的页面?.invoke(request.url.toString())
                return true
            }
        }
        transport.webView = v
        resultMsg.sendToTarget()
        return true
    }

    // 存储当前文件选择的回调
    private var mFilePathCallback: ValueCallback<Array<Uri?>?>? = null
    
    /**
     * 处理文件选择请求
     * 
     * 当网页需要上传文件时调用（如 <input type="file">）
     * 返回 true 表示应用已处理，false 表示使用默认处理
     */
    override fun onShowFileChooser(webView: WebView?, filePathCallback: ValueCallback<Array<Uri?>?>?, fileChooserParams: FileChooserParams?): Boolean {
        if (filePathCallback == null || fileChooserParams == null) return false
        
        // 如果已有未完成的文件选择请求，取消它
        mFilePathCallback?.onReceiveValue(null)
        mFilePathCallback = filePathCallback
        
        try {
            // 获取当前活动的Activity
            val activity = ActivityUtils.getTopActivity() ?: return false
            
            // 构建文件选择Intent
            val intent = fileChooserParams.createIntent()
            
            // 检查是否接受多选
            if (fileChooserParams.mode == FileChooserParams.MODE_OPEN_MULTIPLE) {
                intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
            }
            
            // 处理可接受的MIME类型
            val acceptTypes = fileChooserParams.acceptTypes
            if (acceptTypes.isNotEmpty() && acceptTypes[0].isNotEmpty()) {
                // 判断是否为图片类型
                val isImageOnly = acceptTypes.all { it.startsWith("image/") || it == "image/*" }
                if (isImageOnly) {
                    intent.type = "image/*"
                }
                
                // 判断是否为视频类型
                val isVideoOnly = acceptTypes.all { it.startsWith("video/") || it == "video/*" }
                if (isVideoOnly) {
                    intent.type = "video/*"
                }
                
                // 判断是否为音频类型
                val isAudioOnly = acceptTypes.all { it.startsWith("audio/") || it == "audio/*" }
                if (isAudioOnly) {
                    intent.type = "audio/*"
                }
            }
            
            // 处理文件选择结果的回调
            val fileChooserResultListener = object : ActivityResultCallback<ActivityResult> {
                override fun onActivityResult(result: ActivityResult) {
                    if (result.resultCode == Activity.RESULT_OK) {
                        val data = result.data
                        val results = if (data?.clipData != null) {
                            // 处理多文件选择结果
                            val clipData = data.clipData!!
                            Array<Uri?>(clipData.itemCount) { i ->
                                clipData.getItemAt(i).uri
                            }
                        } else {
                            // 处理单文件选择结果
                            val uri = data?.data
                            if (uri != null) arrayOf<Uri?>(uri) else null
                        }
                        
                        mFilePathCallback?.onReceiveValue(results)
                    } else {
                        // 用户取消了选择
                        mFilePathCallback?.onReceiveValue(null)
                    }
                    mFilePathCallback = null
                }
            }
            
            // 使用ActivityResultLauncher启动文件选择器
            val launcher = (activity as AppCompatActivity).activityResultRegistry
                .register("file_chooser", ActivityResultContracts.StartActivityForResult(), fileChooserResultListener)
            
            launcher.launch(intent)
            return true
        } catch (e: Exception) {
            Log.e("MVueChromeClient", "文件选择器启动失败: ${e.message}", e)
            // 出现异常时，取消文件选择
            filePathCallback.onReceiveValue(null)
            mFilePathCallback = null
            return false
        }
    }

    /**
     * 页面卸载前调用
     * 
     * 当页面即将被卸载时触发（如 window.onbeforeunload 事件）
     * 可用于提示用户是否确认离开页面
     */
    override fun onJsBeforeUnload(view: WebView?, url: String?, message: String?, result: JsResult?): Boolean {
        state.响应销毁页面.invoke()
        return true
    }

    /**
     * WebView 请求获取焦点时调用
     */
    override fun onRequestFocus(view: WebView?) {
        super.onRequestFocus(view)
    }

    /**
     * 获取视频播放的默认海报图像
     * 
     * 当网页中有视频元素但没有指定海报图像时调用
     * 返回一个默认的位图作为视频播放器的占位图
     */
    override fun getDefaultVideoPoster(): Bitmap? {
        return try {
            BitmapFactory.decodeResource(Utils.getApp().baseContext.getResources(), R.mipmap.baidi)
        } catch (e: Exception) {
            super.getDefaultVideoPoster()
        }
    }

    /**
     * 地理位置权限提示被隐藏时调用
     */
    override fun onGeolocationPermissionsHidePrompt() {
        super.onGeolocationPermissionsHidePrompt()
    }

    /**
     * 网页请求地理位置权限时调用
     * 
     * 当网页使用 Geolocation API 请求获取用户位置时触发
     * 应用可以决定是否授予权限，并记住用户的选择
     */
    override fun onGeolocationPermissionsShowPrompt(origin: String?, callback: GeolocationPermissions.Callback?) {
        if (origin == null || callback == null) return
        
        // 常见搜索引擎自动允许定位
        if (origin == "https://m.baidu.com/" 
                || origin.contains("cn.bing.com/search")
                || origin.contains("m.so.com")) {
            callback.invoke(origin, true, true)
            return
        }
        
        // 对其他网站，弹出对话框询问用户
        ActivityUtils.getTopActivity()?.let { activity ->
            // 使用ContextThemeWrapper确保对话框使用AppCompat主题
            val contextThemeWrapper = ContextThemeWrapper(activity, R.style.Theme_Mbrowser4)
            val builder = AlertDialog.Builder(contextThemeWrapper)
                .setTitle("位置信息请求")
                .setMessage("网站 $origin 请求获取您的位置信息。\n\n是否允许？")
                .setPositiveButton("允许") { _, _ ->
                    // 授予权限并记住选择
                    callback.invoke(origin, true, true)
                }
                .setNegativeButton("拒绝") { _, _ ->
                    // 拒绝权限并记住选择
                    callback.invoke(origin, false, true)
                }
                .setCancelable(false)
            builder.show()
        } ?: run {
            // 如果无法显示对话框，默认拒绝
            callback.invoke(origin, false, false)
        }
    }

    /**
     * 网页请求其他权限时调用
     * 
     * 当网页请求访问摄像头、麦克风等权限时触发
     * 应用需要处理权限请求并决定是否授予权限
     */
    override fun onPermissionRequest(request: PermissionRequest?) {
        if (request == null) return

        val resources = request.resources
        val origin = request.origin.toString()
        
        // 构建可读的权限名称映射
        val permissionNames = resources.map { resource ->
            when (resource) {
                PermissionRequest.RESOURCE_AUDIO_CAPTURE -> "麦克风"
                PermissionRequest.RESOURCE_VIDEO_CAPTURE -> "摄像头"
                PermissionRequest.RESOURCE_PROTECTED_MEDIA_ID -> "受保护媒体"
                PermissionRequest.RESOURCE_MIDI_SYSEX -> "MIDI设备"
                else -> "未知权限($resource)"
            }
        }
        
        // 如果没有请求任何权限，直接拒绝
        if (permissionNames.isEmpty()) {
            request.deny()
            return
        }
        
        // 显示权限请求对话框
        ActivityUtils.getTopActivity()?.let { activity ->
            // 使用ContextThemeWrapper确保对话框使用AppCompat主题
            val contextThemeWrapper = ContextThemeWrapper(activity, R.style.Theme_Mbrowser4)
            val builder = AlertDialog.Builder(contextThemeWrapper)
                .setTitle("权限请求")
                .setMessage("网站 $origin 请求使用您的：\n${permissionNames.joinToString("\n")}\n\n是否允许？")
                .setPositiveButton("允许") { _, _ ->
                    // 授予所有请求的权限
                    request.grant(resources)
                }
                .setNegativeButton("拒绝") { _, _ ->
                    // 拒绝所有权限
                    request.deny()
                }
                .setCancelable(false)
            builder.show()
        } ?: run {
            // 如果无法显示对话框，默认拒绝
            request.deny()
        }
    }



    /**
     * 处理 JavaScript 控制台消息
     * 
     * 当网页中的 JavaScript 输出到控制台时调用
     * 可用于记录和调试网页中的 JavaScript 代码
     */
    override fun onConsoleMessage(var1: ConsoleMessage?): Boolean {

        var1?.message()?.let {
            val level = when(var1.messageLevel()){
                MessageLevel.TIP-> 0
                MessageLevel.LOG -> 1
                MessageLevel.WARNING -> 2
                MessageLevel.ERROR -> 3
                MessageLevel.DEBUG -> 4
                else -> 1
            }

            // TODO 调试
        }
        return true
    }

    /**
     * 权限请求被取消时调用
     */
    override fun onPermissionRequestCanceled(request: PermissionRequest?) {
        //App.log("sdfdsf")
        super.onPermissionRequestCanceled(request)
    }

    /**
     * TODO 显示自定义视图时调用 -- 启用全屏媒体
     * 
     * 当网页请求全屏显示视频等内容时触发
     * 应用需要提供一个容器来显示这些自定义视图
     */
    private var nCallback: CustomViewCallback? = null
    override fun onShowCustomView(view: View?, callback: CustomViewCallback?) {
        // TODO 全屏视频
        /*if (PageMg.getFullScreenView() != null) {
            PageMg.closeFullScreen()
            return
        }
        nCallback = callback

        val v = WebwebVideoView(view!!.context)
        v.setBrowser(mWeb,view)

        PageMg.setFullScreen(v, true) {
                isFullScreen: Boolean ->
            if (!isFullScreen && nCallback != null) nCallback!!.onCustomViewHidden()
        }*/
    }

    /**
     * TODO 隐藏自定义视图时调用 -- 取消全屏媒体
     * 
     * 当网页退出全屏模式时触发
     * 应用需要移除之前显示的自定义视图
     */
    override fun onHideCustomView() {
        // PageMg.closeFullScreen()
        nCallback = null
    }


}